/**
 * 
 */
package com.effectiv.req1.controller;

import java.util.List;

import javax.validation.Valid;

import jodd.datetime.JDateTime;
import jodd.util.StringUtil;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.effectiv.req1.business.api.LovService;
import com.effectiv.req1.business.api.ProjectService;
import com.effectiv.req1.business.api.UseCaseService;

import com.effectiv.req1.domain.Note;
import com.effectiv.req1.domain.Project;
import com.effectiv.req1.domain.UseCase;

/**
 * @author Dhrubo
 * 
 */
@Controller
@Slf4j
public class UseCaseController {

	@Autowired
	private UseCaseService useCaseService;

	@Autowired
	private ProjectService projectService;

	@Autowired
	private LovService lovService;

	@RequestMapping(value = "/listusecases")
	public final String showHome(
			@RequestParam(value = "project", required = false) String project,
			@RequestParam(value = "usecase", required = false) String useCase,
			@RequestParam(value = "selection", required = false) boolean selection,
			Model model) {

		if (StringUtil.isEmpty(project)) {

			model.addAttribute("useCases", useCaseService.findUseCases());
		} else {
			model.addAttribute("useCases",
					useCaseService.findByProject(project));
			model.addAttribute(useCaseService.findOne(useCase));
			model.addAttribute("selection", selection);
		}

		return "listusecases";
	}

	@RequestMapping(value = "/newusecase")
	public final String create(Model model) {
		model.addAttribute(BeanUtils.instantiate(UseCase.class));

		List<Project> projects = projectService.findProjects();

		if (projects == null || projects.size() == 0) {
			model.addAttribute("noproject", true);
		} else {
			model.addAttribute("noproject", false);
		}

		model.addAttribute("projects", projectService.findProjects());
		return "newusecase";
	}

	@RequestMapping(value = "/saveusecase", method = RequestMethod.POST)
	public @ResponseBody
	AjaxResponse save(@Valid UseCase useCase, BindingResult result,
			AjaxResponse response) {
		log.info("Saving new user");
		if (!result.hasErrors()) {

			useCaseService.save(useCase);
			response.setResult(useCase);
		} else {
			response.markValidationFailure(result.getFieldErrors());
		}

		log.info("Saving new user - response = {}", response);
		return response;
	}

	@RequestMapping(value = "/editusecase")
	public final String edit(
			@RequestParam(value = "usecase", required = true) String id,
			@RequestParam(value = "active", required = true, defaultValue = "1") int active,
			Model model) {

		model.addAttribute(useCaseService.findOne(id));
		model.addAttribute("active", active);

		return "editusecase";
	}

	@RequestMapping(value = "/updateusecase")
	public final String update(@Valid UseCase useCase, BindingResult result,
			Model model) {
		UseCase useCaseTarget = useCaseService.update(useCase);
		model.addAttribute(useCaseTarget);
		model.addAttribute("active", 1);

		return "editusecase";
	}

	@RequestMapping(value = "/viewusecase")
	public final String view(
			@RequestParam(value = "usecase", required = true) String id,
			Model model) {
		model.addAttribute(useCaseService.findOne(id));
		return "viewusecase";
	}

	@RequestMapping(value = "/updatemainflow")
	public @ResponseBody
	String editMainFlowStep(@RequestParam("pk") String id,
			@RequestParam("name") int rowNum,
			@RequestParam("value") String value, Model model) {

		UseCase useCase = useCaseService.editMainFlowStep(id, rowNum, value);
		model.addAttribute(useCase);
		model.addAttribute("active", 6);

		return "editusecase";
	}

	@RequestMapping(value = "/addmainflow")
	public String addUseCaseMainFlowStepDescription(
			@RequestParam("id") String id,
			@RequestParam("description") String description, Model model) {
		log.debug("Use case id = {}", id);
		log.debug("Row num id = {}", description);
		UseCase useCase = useCaseService.addUseCaseMainFlowStepDescription(id,
				description);
		model.addAttribute(useCase);
		model.addAttribute("active", 6);
		return "editusecase";
	}

	@RequestMapping(value = "/moveup")
	public String moveUp(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);
		UseCase useCase = useCaseService.move(id, index, true);
		model.addAttribute(useCase);
		model.addAttribute("active", 6);

		return "editusecase";
	}

	@RequestMapping(value = "/movedown")
	public String moveDown(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);
		UseCase useCase = useCaseService.move(id, index, false);
		model.addAttribute(useCase);
		model.addAttribute("active", 6);

		return "editusecase";
	}

	@RequestMapping(value = "/deleteucstep")
	public String delete(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);
		UseCase useCase = useCaseService.deleteMainFlowStep(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 6);

		return "editusecase";
	}

	@RequestMapping(value = "/newalternate")
	public String newAlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);
		UseCase useCase = useCaseService.addAlternateFlow(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 7);
		return "editusecase";
	}

	@RequestMapping(value = "/addalternateflowstep")
	public String addAlternateFlowStepDescription(
			@RequestParam("description") String description,
			@RequestParam("id") String id, @RequestParam("stepid") int stepid,
			@RequestParam("flowid") int flowid, Model model) {
		log.info("description = {}", description);
		log.info("id = {}", id);
		log.info("stepid = {}", stepid);
		log.info("flowid = {}", flowid);

		UseCase useCase = useCaseService.addAlternateFlowStepDescription(
				description, id, stepid, flowid);
		model.addAttribute(useCase);
		model.addAttribute("active", 7);
		model.addAttribute("pos", "alt" + stepid + "" + flowid);
		return "editusecase";

	}

	@RequestMapping(value = "/moveupalternate")
	public String moveUpAlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index,
			@RequestParam("flowid") int flowid,
			@RequestParam("stepid") int stepid, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);
		UseCase useCase = useCaseService.moveAlternate(id, index, flowid,
				stepid, true);
		model.addAttribute(useCase);
		model.addAttribute("active", 7);
		model.addAttribute("pos", "alt" + stepid + "" + flowid);
		return "editusecase";
	}

	@RequestMapping(value = "/movedownalternate")
	public String moveDownlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index,
			@RequestParam("flowid") int flowid,
			@RequestParam("stepid") int stepid, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseService.moveAlternate(id, index, flowid,
				stepid, false);
		model.addAttribute(useCase);
		model.addAttribute("active", 7);
		model.addAttribute("pos", "alt" + stepid + "" + flowid);
		return "editusecase";
	}

	@RequestMapping(value = "/deletestepalternate")
	public String deleteStepAlternate(@RequestParam("usecase") String id,
			@RequestParam("index") int index,
			@RequestParam("flowid") int flowid,
			@RequestParam("stepid") int stepid, Model model) {
		log.info("Use case id = {}", id);
		log.info("Row num id = {}", index);

		UseCase useCase = useCaseService.deleteAlternateStep(id, index, flowid,
				stepid);
		model.addAttribute(useCase);
		model.addAttribute("active", 7);
		model.addAttribute("pos", "alt" + stepid + "" + flowid);
		return "editusecase";

	}

	@RequestMapping(value = "/addprecondition")
	public String addPreCondition(@RequestParam("usecase") String id,
			@RequestParam("description") String description, Model model) {

		UseCase useCase = useCaseService
				.appendCondition(id, description, false);
		model.addAttribute(useCase);
		model.addAttribute("active", 3);
		return "editusecase";
	}

	@RequestMapping(value = "/addpostcondition")
	public String addPostCondition(@RequestParam("usecase") String id,
			@RequestParam("description") String description, Model model) {

		UseCase useCase = useCaseService.appendCondition(id, description, true);
		model.addAttribute(useCase);
		model.addAttribute("active", 3);
		return "editusecase";
	}

	@RequestMapping(value = "/appendactor")
	public String appendActor(@RequestParam("usecase") String id,
			@RequestParam("actor") int index, Model model) {
		UseCase useCase = useCaseService.appendActor(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 2);
		return "editusecase";
	}

	@RequestMapping(value = "/deletecondition")
	public String deleteCondition(@RequestParam("usecase") String id,
			@RequestParam("index") int index, @RequestParam("pre") boolean pre,
			Model model) {
		UseCase useCase = useCaseService.deleteCondition(id, index, pre);
		model.addAttribute(useCase);
		model.addAttribute("active", 3);
		return "editusecase";
	}

	@RequestMapping(value = "/savepriority")
	public String savePriority(@RequestParam("usecase") String id,
			@RequestParam("priority") String priority, Model model) {
		UseCase useCase = useCaseService.addPriority(id, priority);
		model.addAttribute(useCase);
		model.addAttribute("active", 4);
		return "editusecase";
	}

	@RequestMapping(value = "/savefrequency")
	public String saveFrequency(@RequestParam("usecase") String id,
			@RequestParam("times") int times,
			@RequestParam("unit") String unit, Model model) {
		UseCase useCase = useCaseService.saveFrequency(id, times, unit);
		model.addAttribute(useCase);
		model.addAttribute("active", 5);
		return "editusecase";
	}

	@RequestMapping(value = "/addassumption")
	public String addassumption(@RequestParam("usecase") String id,
			@RequestParam("description") String description, Model model) {
		UseCase useCase = useCaseService.addAssumption(id, description);
		model.addAttribute(useCase);
		model.addAttribute("active", 11);
		return "editusecase";
	}

	@RequestMapping(value = "/deleteassumption")
	public String deleteassumption(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		UseCase useCase = useCaseService.deleteAssumption(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 11);
		return "editusecase";
	}

	@RequestMapping(value = "/deleteactor")
	public String deleteActor(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		UseCase useCase = useCaseService.deleteActor(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 2);
		return "editusecase";
	}

	@RequestMapping(value = "/addexception")
	public String addaException(@RequestParam("usecase") String id,
			@RequestParam("description") String description, Model model) {
		UseCase useCase = useCaseService.addException(id, description);
		model.addAttribute(useCase);
		model.addAttribute("active", 8);
		return "editusecase";
	}

	@RequestMapping(value = "/deleteexception")
	public String deleteException(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		UseCase useCase = useCaseService.deleteException(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 8);
		return "editusecase";
	}

	@RequestMapping(value = "/includeusecase")
	public String includeuc(@RequestParam("usecase") String id,
			@RequestParam("incuc") String includedUcId, Model model) {
		UseCase useCase = useCaseService.includeUseCase(id, includedUcId);
		model.addAttribute(useCase);
		model.addAttribute("active", 9);
		return "editusecase";
	}

	@RequestMapping(value = "/deleteinclude")
	public String deleteInclud(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		UseCase useCase = useCaseService.deleteInclude(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 9);
		return "editusecase";
	}

	@RequestMapping(value = "/addspecial")
	public String addaSpecial(@RequestParam("usecase") String id,
			@RequestParam("description") String description, Model model) {
		UseCase useCase = useCaseService.addSpecial(id, description);
		model.addAttribute(useCase);
		model.addAttribute("active", 10);
		return "editusecase";
	}

	@RequestMapping(value = "/deletespecial")
	public String deleteSpecial(@RequestParam("usecase") String id,
			@RequestParam("index") int index, Model model) {
		UseCase useCase = useCaseService.deleteSpecial(id, index);
		model.addAttribute(useCase);
		model.addAttribute("active", 10);
		return "editusecase";
	}

	@RequestMapping(value = "/appendnote")
	public String appendNote(@RequestParam("description") String description,@RequestParam("priority") String priority,
			@RequestParam("targetDate") String targetDate,
			@RequestParam("usecase") String id,
			@RequestParam("user") String user, Model model) {
		
		//few manual validations required here
		JDateTime tDate = new JDateTime(targetDate, "DD/MM/YYYY");
		//TODO validate date here
		
		UseCase useCase = useCaseService.addNote(id, user, tDate.convertToDate(), description, priority);
		model.addAttribute(useCase);
		model.addAttribute("active", 12);
		return "editusecase";
	}
}
